/**
*  \file direction_switch.c
*
*  \brief
*
*  \author Michael J. Hohmann  <michael.hohmann@linde-mh.de>
*
*
*/

/*===============================================[ private includes  ]================================================*/
#include "direction_switch.h"
#include "../assertor/assertor.h"
#include "../pal/pal_mem.h"
#include "../saturated/sinc.h"
#include "../keytime/keytime.h"

/*===============================================[ private defines   ]================================================*/
#define DIRECTION_SWITCH_FWRD_DEBOUNCE S16_CONST( 0x0003 )
#define DIRECTION_SWITCH_REVS_DEBOUNCE S16_CONST( 0x0003 )
#define DIRECTION_SWITCH_NTL_DEBOUNCE S16_CONST( 0x0003 )

#define DIRECTION_SWITCH_ERROR_TICK S16_CONST( 5 )

/*===============================================[ private datatypes ]================================================*/

/*===============================================[ private variables ]================================================*/

/*===============================================[ private functions ]================================================*/

/*================================================[ inline functions ]================================================*/

/*================================================[ public functions ]================================================*/

RC direction_switch_construct( struct direction_switch_obj *me )
{   
   ASSERTOR_PRE( NIL != me,"NIL is not allowed as object pointer." );
   pal_memzero( me, sizeof *me );

   me->current_state=direction_switch_state_invalid;
   me->current_error=direction_switch_error_none;

   return RC_SUCCESS;
}


static void direction_switch_process_errors( struct direction_switch_obj *me )
{
   /* error detection */
      if( (me->fwd_tick_count > DIRECTION_SWITCH_ERROR_TICK) && (me->bwd_tick_count > DIRECTION_SWITCH_ERROR_TICK) )
      {
         me->current_error = direction_switch_error_fw_and_bw_acktive;
      }

      if ( me->current_error != direction_switch_error_none)
      {
         // error counter ++
      }
};


void direction_switch_process( struct direction_switch_obj *me, BO fwd, BO ntl , BO bwd )
{

   me->ticks_in_current_state = sinc_u16( me->ticks_in_current_state  ); /* if state will change this value will be set to 0 later */

   me->fwd_tick_count = keytime(  fwd, me->fwd_tick_count );
   me->bwd_tick_count = keytime(  bwd, me->bwd_tick_count );
   me->ntl_tick_count = keytime(  ntl, me->ntl_tick_count );

   //direction_switch_process_errors( me );

   switch( me->current_state )
   {
      case direction_switch_state_neutral :
      {
            if( me->fwd_tick_count > DIRECTION_SWITCH_FWRD_DEBOUNCE )
            {
               me->fwd_tick_count = 0;
               me->ticks_in_current_state = 0;
               me->current_state=direction_switch_state_forward;
            }

            if( me->bwd_tick_count > DIRECTION_SWITCH_REVS_DEBOUNCE )
            {
               me->bwd_tick_count = 0;
               me->ticks_in_current_state = 0;
               me->current_state=direction_switch_state_reverse ;
            }
            break;
      }
      case direction_switch_state_forward :
      {
          if( me->ntl_tick_count > DIRECTION_SWITCH_NTL_DEBOUNCE )
          {
             me->ntl_tick_count = 0;
             me->ticks_in_current_state = 0;
             me->current_state=direction_switch_state_neutral;
          }

          if( me->bwd_tick_count > DIRECTION_SWITCH_REVS_DEBOUNCE )
          {
             me->bwd_tick_count = 0;
             me->ticks_in_current_state = 0;
             me->current_state=direction_switch_state_reverse ;
          }
          break;
      }
      case direction_switch_state_reverse :
      {
          if( me->ntl_tick_count > DIRECTION_SWITCH_NTL_DEBOUNCE )
          {
             me->ntl_tick_count = 0;
                 me->ticks_in_current_state = 0;
                 me->current_state=direction_switch_state_neutral;
          }

          if( me->fwd_tick_count > DIRECTION_SWITCH_FWRD_DEBOUNCE )
          {
             me->fwd_tick_count = 0;
             me->ticks_in_current_state = 0;
             me->current_state=direction_switch_state_forward;
          }
          break;
      }
      case direction_switch_state_invalid :
      {
         if( me->ntl_tick_count > 10 )
         {
            me->current_state=direction_switch_state_neutral;
         }
         break;
      }
      default: { ASSERTOR_ILLEGAL_DEFAULT( "state is out of expected range" );}
   }
}

enum direction_switch_state direction_switch_get_state( struct direction_switch_obj const * me, U16 *p_state_time )
{
   if( NIL != p_state_time )
   {
      *p_state_time = me->ticks_in_current_state;
   }

   return me->current_state;
}


enum direction_switch_error direction_switch_get_error( struct direction_switch_obj const * me, U16 *p_error_time )
{
   if( NIL != p_error_time )
   {
      *p_error_time = me->ticks_in_current_error;
   }

   return me->current_error;
}


/*===============================================[ private functions ]================================================*/


/***********************************************************************************************************************
*                             Copyright 2019 Linde Material Handling. All rights reserved.                             *
***********************************************************************************************************************/
